package com.weather.data.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.weather.data.dao.SkyElementMapper;
import com.weather.data.dao.SkyEngineMapper;
import com.weather.data.dao.SkyParameterMapper;
import com.weather.data.entity.DO.SkyElement;
import com.weather.data.entity.DO.SkyEngine;
import com.weather.data.entity.DO.SkyParameter;
import com.weather.data.entity.VO.SkyEnginePageVO;
import com.weather.data.entity.VO.SkyEngineRespVO;
import com.weather.data.entity.VO.SkyEngineSaveVO;
import com.weather.data.service.SkyEngineService;
import com.weather.data.utils.RestUtil;
import com.weather.data.utils.SignGenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 天擎-接口信息 服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2024-12-24
 */
@Service
public class SkyEngineServiceImp extends ServiceImpl<SkyEngineMapper, SkyEngine> implements SkyEngineService {

    @Resource
    private SkyEngineMapper skyEngineMapper;

    @Resource
    private SkyParameterMapper skyParameterMapper;

    @Resource
    private SkyElementMapper skyElementMapper;

    @Override
    public Long addSkyEngine(SkyEngineSaveVO skyEngineSaveVO) {
        SkyEngine skyEngine = new SkyEngine();
        BeanUtils.copyProperties(skyEngineSaveVO, skyEngine);
        skyEngineMapper.insert(skyEngine);
        skyEngineSaveVO.getSkyParameters().forEach(parameter -> {
            parameter.setSkyId(skyEngine.getId());
        });
        List<SkyParameter> skyParameters = skyEngineSaveVO.getSkyParameters();
        for (SkyParameter skyParameter : skyParameters) {
            skyParameterMapper.insert(skyParameter);
        }
        return skyEngine.getId();
    }

    @Override
    public Boolean delSkyEngineByIds(List<Long> ids) {
        int i = skyEngineMapper.deleteBatchIds(ids);
        return i == ids.size();
    }

    @Override
    public Boolean updateSkyEngine(SkyEngineSaveVO skyEngineSaveVO) {
        SkyEngine skyEngine = new SkyEngine();
        BeanUtils.copyProperties(skyEngineSaveVO, skyEngine);
        skyEngineMapper.updateById(skyEngine);
        if (skyEngineSaveVO.getSkyParameters() != null) {
            List<SkyParameter> skyParameters = skyEngineSaveVO.getSkyParameters();
            for (SkyParameter skyParameter : skyParameters) {
                if (skyParameter.getId()!=null) {
                    skyParameterMapper.updateById(skyParameter);
                }else {
                    skyParameterMapper.insert(skyParameter);
                }
            }
        }
        return true;
    }

    @Override
    public IPage<SkyEngine> getSkyEnginePage(SkyEnginePageVO skyEnginePageVO) {
        IPage<SkyEngine> iPage = new Page<>(skyEnginePageVO.getPageNo(), skyEnginePageVO.getPageSize());
        return skyEngineMapper.getSkyEnginePage(iPage,skyEnginePageVO);
    }

    @Override
    public SkyEngineRespVO getSkyEngineAndParameter(Long id) {
        SkyEngine skyEngine = skyEngineMapper.selectById(id);
        SkyEngineRespVO skyEngineRespVO = new SkyEngineRespVO();
        BeanUtils.copyProperties(skyEngine, skyEngineRespVO);
        List<SkyElement> skyElements = skyElementMapper.selectList(Wrappers.<SkyElement>lambdaQuery().eq(SkyElement::getSkyId, id));
        skyEngineRespVO.setElements(skyElements);
        List<SkyParameter> skyParameters = skyParameterMapper.selectList(Wrappers.<SkyParameter>lambdaQuery().eq(SkyParameter::getSkyId, id));
        skyEngineRespVO.setSkyParameters(skyParameters);
        return skyEngineRespVO;
    }


    @Override
    public String downloadFile(SkyEngineRespVO skyEngineRespVO) {
        // 用户id
        String userId = "XA_QXDN";
        // 密码
        String password = "Xionganqixiang@2023";
        // 接口id
        String interfaceId = skyEngineRespVO.getInterfaceId();
        // 数据代码
        String dataCode = skyEngineRespVO.getDataCode();
        // 要素名称
        String inputElements = skyEngineRespVO.getInputElements();
        // 服务节点
        String serviceNodeId = skyEngineRespVO.getServiceNodeId();
        // 用户输入的参数
        AtomicReference<String> inputParameter = new AtomicReference<>("");
        List<SkyParameter> skyParameters = skyEngineRespVO.getSkyParameters();
        // 由参数列表生成sign
        HashMap<String, String> signParam = new HashMap<String, String>();
        skyParameters.forEach(parameter -> {
            inputParameter.set(inputParameter + parameter.getParameterId() + "=" + parameter.getValue() + "&");
            signParam.put(parameter.getParameterId(), parameter.getValue());
        });
        String parameters = inputParameter.toString();
        parameters = parameters.substring(0, parameters.length() - 1);

        /* 1. 调用方法的参数定义，并赋值 */
        String params = "serviceNodeId=" + serviceNodeId + "&userId=" + userId /* 1.1 用户名 */ + "&interfaceId=" + interfaceId /* 1.2 接口ID */ + "&dataCode=" + dataCode /* 1.3 必选参数（按需加可选参数） */ //资料：中国地面逐小时
                + "&elements=" + inputElements + "&dataFormat=csv" + "&" + parameters; /* 1.4 序列化格式 */
        //拼接timestamp、nonce
        String timestamp = String.valueOf(System.currentTimeMillis());
        String nonce = UUID.randomUUID().toString();
        params += "&timestamp=" + timestamp;
        params += "&nonce=" + nonce;

        signParam.put("serviceNodeId", serviceNodeId);
        signParam.put("userId", userId);
        signParam.put("interfaceId", interfaceId);
        signParam.put("dataCode", dataCode);
        signParam.put("elements", inputElements);
        signParam.put("dataFormat", "csv");
        signParam.put("timestamp", timestamp);
        signParam.put("nonce", nonce);
        signParam.put("pwd", password);
        String sign = SignGenUtil.getSign(signParam);
        params += "&sign=" + sign;

        /* 2. 调用接口 */
        RestUtil restUtil = new RestUtil();
        String rstData = restUtil.getRestData(params);
        return rstData;

/*        // 解析JSON数据
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(jsonObject.get("DS").toString());
        String csvContent = convertToCsv(jsonNode); // 假设这个方法将JsonNode转换为CSV格式的字符串
        // 设置响应头
        String fileName = "接口返回数据.csv";
        response.setContentType("text/csv; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8"));
        // 使用ByteArrayOutputStream来捕获CSV内容
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)) {
            PrintWriter out = new PrintWriter(writer, true);
            // 写入CSV文件的头部
            out.println(fieldNames); // 假设fieldNames是包含CSV表头的字符串
            // 写入CSV内容
            out.write(csvContent);
            // 注意：这里不需要再次调用out.flush()，因为PrintWriter在try-with-resources语句结束时会自动关闭和刷新
        }
        // 将ByteArrayOutputStream的内容写入到响应的输出流中
        byteArrayOutputStream.writeTo(response.getOutputStream());*/
    }


    private String convertToCsv(JsonNode jsonNode) {
        StringBuilder csvContent = new StringBuilder();
        // 写入数据行
        for (JsonNode jsonRow : jsonNode) {
            Iterator<Map.Entry<String, JsonNode>> rowFields = jsonRow.fields();
            if (rowFields.hasNext()) {
                Map.Entry<String, JsonNode> entry = rowFields.next();
                csvContent.append("\"").append(entry.getValue().asText()).append("\"");
                while (rowFields.hasNext()) {
                    entry = rowFields.next();
                    csvContent.append(",\"").append(entry.getValue().asText()).append("\"");
                }
                csvContent.append("\n");
            }
        }

        return csvContent.toString();
    }
}

